package com.tansty.web.config.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author: Tansty
 * @Date: 2021/7/13 22:17
 * @Description:
 */
@Aspect
@Slf4j
@Component
public class ControllerAspect {
    private static final int MAX_TIME = 5000; // 超过这个时间，接口访问过慢

    public Object runAndSaveLog(ProceedingJoinPoint pjp) throws Throwable {
        long beginTime = System.currentTimeMillis();
        // 获取当前对象
        String userId = "无";
        String username = "无";
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return pjp.proceed();
        }

        HttpServletRequest req = attributes.getRequest();

        String host = req.getRemoteHost();


        Object result = null;
        // 获取目标对象
        Object target = pjp.getTarget();
        // 获取方法签名对象
        Signature signature = pjp.getSignature();

        try {
            result = pjp.proceed();
        } catch (Throwable e) {
            // ------------------------------------ //

            log.error("------------------------------------------");
            log.error("Controller : " + target.getClass().getSimpleName());
            log.error("方法 : " + signature);
            log.error("错误原因 : " + e.getMessage());
            log.error("调用者Id : " + userId);
            log.error("调用者用户名 : " + username);
            log.error("调用者IP : " + host);
            throw e;

            // ------------------------------------ //
        }

        // ------------------------------------ //

        long endTime = System.currentTimeMillis();
        log.info("------------------------------------------");
        log.info("Controller : " + target.getClass().getSimpleName());
        log.info("方法 : " + signature.getName());
        log.info("本方法用时 : " + (endTime - beginTime));
        //  记录谁访问了这个接口，已登录用户
        log.info("调用者Id : " + userId);
        log.info("调用者用户名 : " + username);
        log.info( "调用者IP : " + host);
        //  还可以判断接口时间，统计slowRequest
        if (endTime - beginTime > MAX_TIME){
            long outTime = endTime - beginTime - MAX_TIME;
            log.warn("------------------------------------------");
            log.warn("Controller : " + target.getClass().getSimpleName());
            log.warn("方法 : " + signature.getName());
            log.warn( "接口调用过慢，已超时 : " + outTime + "毫秒");
        }

        // ------------------------------------ //
        return result;

    }

    @Around("@within(org.springframework.stereotype.Controller)")
    Object aroundController(ProceedingJoinPoint pjp) throws Throwable {
        return runAndSaveLog(pjp);
    }

    @Around("@within(org.springframework.web.bind.annotation.RestController)")
    Object aroundRestController(ProceedingJoinPoint pjp) throws Throwable {
        return runAndSaveLog(pjp);
    }

}
